<template>
    <div class="field-editor-box">
        <div class="field-editor-toolbar">
            <el-row :gutter="10">


                <el-col :span="1.5">
                    <el-tooltip effect="light" content="添加" placement="top-start">
                        <el-button icon="el-icon-plus" plain circle size="small" @click="inserFieldHandle" />
                    </el-tooltip>
                </el-col>

                <el-col :span="1.5">
                    <el-tooltip effect="light" content="删除" placement="top-start">
                        <el-button icon="el-icon-minus" plain circle size="small" @click="deleteFieldHandle" />
                    </el-tooltip>
                </el-col>


            </el-row>
        </div>
        <vxe-table :data="table.fields" size="mini" border stripe :keep-source="true" height="100%" ref="xTable"
           :loading="tableLoading"
            class="mytable-scrollbar" :column-config="{ resizable: true }" mouse-config="{area:true}"
            :row-config="{ isHover: true, isCurrent: true }" :keyboard-config="{ isClip: true, isDel: true }"
            :edit-config="{ trigger: 'click', mode: 'row', enabled: true }" :scroll-y="{ enabled: tru }"
            @cell-click="tableDesignCellHandle">
            <vxe-column type="seq" width="60"></vxe-column>
            <vxe-column field="name" title="名字" show-header-overflow="title" show-overflow="title" width="200"
                :edit-render="{ autofocus: '.vxe-input--inner' }">
                <template #edit="{ row }">
                    <vxe-input v-model="row.name" type="text" @blur="fieldNameBlurHandle(row)" clearable></vxe-input>
                </template>
            </vxe-column>
            <vxe-column field="type" title="类型" show-header-overflow="title" show-overflow="title" width="120"
                :edit-render="{ autofocus: '.vxe-input--inner', events: { change: selectChange } }"><template
                    #edit="{ row }">
                    <!-- <vxe-input v-model="row[type]" type="text"></vxe-input> -->
                    <vxe-select v-model="row.type" filterable @change="fieldTypeChangeHandle(row)" clearable
                        @focus="fieldTypeChangeHandle(row)">
                        <vxe-option v-for="item in dataType" :key="item.name" :value="item.name"
                            :label="item.name"></vxe-option>
                    </vxe-select>
                </template></vxe-column>
            <vxe-column field="size" title="长度" show-header-overflow="title" show-overflow="title" width="120"
                :edit-render="{ autofocus: '.vxe-input--inner' }"><template #edit="{ row }">
                    <vxe-input v-model="row.size" type="number" :max="row.maxSize ? row.maxSize : 10000000000"></vxe-input>
                </template></vxe-column>
            <vxe-column field="decimalDigits" title="小数点" show-header-overflow="title" show-overflow="title" width="120"
                :edit-render="{ autofocus: '.vxe-input--inner' }"><template #edit="{ row }">
                    <vxe-input v-model="row.decimalDigits" type="number" clearable
                        :max="row.maxDecimalDigits ? row.maxDecimalDigits : 10000000000"></vxe-input>
                </template></vxe-column>
            <vxe-column field="nullable" title="为空" show-header-overflow="title" show-overflow="title" width="80"
                :edit-render="{ autofocus: '.vxe-input--inner' }">
                <template #default="{ row, rowIndex }">
                    {{ row.primaryKey?'是':'否' }}
                </template>
                <template #edit="{ row }">
                    <el-checkbox v-model="row.nullable"></el-checkbox>
                </template></vxe-column>
            <vxe-column field="primaryKey" title="主键" show-header-overflow="title" show-overflow="title" width="80"
                :edit-render="{ autofocus: '.vxe-input--inner' }">
                <template #default="{ row, rowIndex }">
                    {{ row.primaryKey?'是':'否' }}
                </template>
                <template #edit="{ row }">
                    <el-checkbox v-model="row.primaryKey" @change="primaryKeyChangeHandle(row)" clearable></el-checkbox>
                </template></vxe-column>
            <vxe-column field="comment" title="注释" show-header-overflow="title" show-overflow="title" width="300"
                :edit-render="{ autofocus: '.vxe-input--inner' }"><template #edit="{ row }">
                    <vxe-input v-model="row.comment" type="text" clearable></vxe-input>
                </template></vxe-column>
            <!-- <vxe-column title="操作" width="100" show-overflow>
                                <template #default="{ row }">
                                    <vxe-button type="text" @click="otherSetConfig(row)">其他</vxe-button>
                                </template>
                            </vxe-column> -->
        </vxe-table>
        <div class="other-set-box">
            <el-form ref="rowOtherFormRef" :model="rowData" label-width="80px" size="small">
                <el-form-item :label="item.name" :prop="item.key" v-for="item in rowOtherFormConfigData.other">
                    <el-select v-model="rowData[item.key]" clearable filterable v-if="item.type === 'select'"
                        @change="updateRowEditState">
                        <el-option v-for="eo in item.data(rowData)" :key="eo.value" :label="eo.name" :value="eo.value" />
                    </el-select>
                    <el-checkbox v-model="rowData[item.key]" clearable v-if="item.type === 'checkbox'"
                        @change="updateRowEditState" />
                    <el-input v-model="rowData[item.key]" clearable v-if="item.type === 'input'" />
                    <el-input-number v-model="rowData[item.key]" controls-position="right" :min="0"
                        v-if="item.type === 'number'"></el-input-number>
                </el-form-item>
            </el-form>
        </div>

    </div>
</template>
<script setup>
import { ref, defineProps, nextTick, inject, defineEmits, reactive, watch,  defineExpose } from "vue"
import { dataType } from "../../service/constant"
import {MetadataService} from "../../service/metadataService"
const props = defineProps({
    connId: {
        type: [String, Number],
        required: true,
        default: undefined
    },
    catalogName: {
        type: String,
        default: undefined
    },
    name: {
        type: String,
        default: undefined
    }
});
const $sqlFormat = inject("$sqlFormat")
const $request = inject('$request');
const $message = inject('$message');
const $messageBox = inject('$messageBox');
const $bus = inject("$bus")
const $config = inject("$config")
const $keymaster = inject("$keymaster");
const metadataService = new MetadataService($request,$message)
const dataTypeConst = dataType;
const copyCacheRow = ref("")
const table = ref({
    catalogName: props.catalogName,
    name: props.name,
    fields: []
})
const xTable = ref(null);
const tableLoading = ref(false)
const createState = ref(!props.tableName);
const rowData = ref({});
const rowOtherFormConfigData = ref({});
const updateFieldData = ref({});



const inserFieldHandle = (item) => {
    const row = -1;

    let record = {
        checked: false,
        name: '', type: '', size: null, decimalDigits: null, nullable: true, primaryKey: false, comment: ''
    }
    if (item) {
        record = item;
    }
    table.value.fields.push(record)
    xTable.value.insertAt(record, row).then(({ row }) => {
        xTable.value.setEditRow(rowData)
    })
}

const deleteFieldHandle = () => {
    const row = xTable.value.getCurrentRecord();
    if (!row) {
        $message.warning("请选择一行数据");
        return
    }
    $messageBox.confirm(
        `确定要删除[${row.name}]?`,
        '消息', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }
    )
        .then(() => {
            xTable.value.removeCurrentRow()
            return true
        })
        .catch((e) => {
            return true;
        })
}










const getTableCloumns = () => {
    xTable.value&& xTable.value.clearAll();
    updateFieldData.value = {};
    tableLoading.value = true;
    metadataService.getTableColumns( props.connId,table.value.catalogName, table.value.name)
    .then(result=>{
        table.value.fields=[];
                for (const row of result.rows) {
                    table.value.fields.push(rowCovert(row))
                }
    })
    .finally(()=>{
            tableLoading.value = false;
        })
  
}

const rowCovert = (row) => {
    let rowCover = {};
    rowCover.key = row.name
    rowCover.name = row.name;
    rowCover.column_default = row.clolumn_default;
    if (row.column_default === '0x') {
        rowCover.column_default = 'EMPTY_STRING'
    }
    rowCover.nullable = row.nullable === 'YES';
    rowCover.type = row.type;
    rowCover.CHARSET = row.CHARACTER_SET_NAME;
    rowCover.COLLATION = row.COLLATION_NAME;
    rowCover.comment = row.COLUMN_COMMENT;

    if (row.COLUMN_KEY) {
        rowCover.primaryKey = true;
        rowCover.oldPrimaryKey = true;
    } else {
        rowCover.primaryKey = false;
        rowCover.oldPrimaryKey = false;
    }
    if (row.COLUMN_TYPE) {
        const arr = findSizeAnddecimalDigits(row.COLUMN_TYPE)
        if (arr.length === 1) {
            rowCover.size = arr[0];
        }
        if (arr.length === 2) {
            rowCover.size = arr[0];
            rowCover.decimalDigits = arr[1];
        }
        const columnType = row.COLUMN_TYPE.toUpperCase();
        if (columnType.indexOf('UNSIGNED') != -1) {
            rowCover.unsigned = true;
        }
        if (columnType.indexOf('ZEROFILL') != -1) {
            rowCover.zerofill = true;
        }
        
    }
    if (row.EXTRA) {
        const d = row.EXTRA.toLowerCase();
        if (d.indexOf('auto_increment') != -1) {
            rowCover.auto_increment = true;
        }
        if (d.indexOf('current_timestamp') != -1) {
            rowCover.CURRENT_TIMESTAMP = true;
        }
    }
    const dtConst = dataTypeConst.find(item => item.name == rowCover.type);
    if (dtConst && dtConst.parserField) {
        dtConst.parserField(row, rowCover)
    }
    fieldTypeChangeHandle(row)
    return rowCover;

}


const findSizeAnddecimalDigits = (columnType) => {
    const arr = [];
    if (columnType.indexOf("(") == -1) {
        return arr;
    }
    const matchResult = columnType.match(/\(.*?\)/g)
    if (!matchResult || matchResult.length == 0) {
        return [];
    }
    return matchResult[0].replace("(", "").replace(")", "").split(",");
}



const primaryKeyChangeHandle = (row) => {
    if (row.primaryKey) {
        row.nullable = false;
    }
}




const getChangeData = () => {
    if (createState.value) {
        return xTable.value.getTableData().fullData;
    }
    let changeFieldData = xTable.value.getRecordset();
    for (const key in updateFieldData.value) {
        if (!changeFieldData.updateRecords.some(item => item.key === key)) {
            changeFieldData.updateRecords.push(updateFieldData.value[key])
        }
    }
    return changeFieldData;
}

const selectChange = (row) => {
    this.$refs.xTable.clearActived()//清除单元格激活状态
    this.$refs.xTable.setActiveCell(row.row, row.column.property)//设置单元格为激活状态
}

const tableDesignCellHandle = ({ row, rowIndex, column }) => {
    if (row.type) {
        rowOtherFormConfigData.value = dataTypeConst.find(item => item.name == row.type);
        rowData.value = row;

    }

}

const fieldTypeChangeHandle = (row) => {
    let dataType1 = dataTypeConst.find(item => item.name == row.type);
    if (dataType1 && dataType1.size) {
        rowOtherFormConfigData.value = dataType1;
        row.maxSize = dataType1.size;
        row.maxDecimalDigits = dataType1.decimalDigits;
        row.size = row.size ? row.size : dataType1.defaultSize;
        row.decimalDigits = row.decimalDigits ? row.decimalDigits : dataType1.defaultDecimalDigits;
    }
}
const fieldNameBlurHandle = (row) => {
    if (!row.name || row.type) {
        return;
    }
    if (row.name.toUpperCase().indexOf('DATE') != -1 || row.name.toUpperCase().indexOf('TIME') != -1) {
        row.type = 'datetime'
        fieldTypeChangeHandle(row)
        return
    }
    if (row.name.toUpperCase().indexOf('ID') != -1) {
        row.type = 'int'
        fieldTypeChangeHandle(row)
        return
    }
    row.type = 'varchar'
    fieldTypeChangeHandle(row)
}


const getFullFields = ()=>{
    return xTable.value.getTableData().fullData;
}

//页面初始化方法
const init = () => {
    watch(
        rowData,
        (newValue, oldValue) => {
            if (newValue._X_ROW_KEY && oldValue._X_ROW_KEY && newValue._X_ROW_KEY === oldValue._X_ROW_KEY) {
                updateFieldData.value[newValue.key] = newValue;
            }
        },
        { deep: true }
    )

    watch(table, () => {
        $bus.$emit("filedsUpdateKey", table.value.fields)
    }, { deep: true })
    nextTick(() => {
        $keymaster('ctrl+c', () => {

            const row = xTable.value.getCurrentRecord();
            if (!row) {
                return
            }
            copyCacheRow.value = JSON.parse(JSON.stringify(row));
            delete copyCacheRow.value._X_ROW_KEY;
            // xTableValue.clearCurrentRow();
            return true
        });
        $keymaster('ctrl+v', () => {
            if (copyCacheRow.value) {
                const row = xTable.value.getCurrentRecord();
                if (row == null || !xTable.value.isEditByRow(row)) {
                    inserFieldHandle(copyCacheRow.value);
                } else {
                    Object.assign(row, copyCacheRow.value)
                    xTable.value.setCurrentRow(row)
                }

            }
            return true
        });
    })
    //如果表名已经传入，那么就不是新建表，需要从后台拉回表的元数据
    if (table.value.catalogName && table.value.name) {
        createState.value = false;
        getTableCloumns();
    }else{
        table.value.fields.push({ name: '', type: '', size: null, decimalDigits: null, nullable: true, primaryKey: false, comment: '' })
    }

}
init();
//重新刷新组件
const reload = () => {
    init();

}
//设置可访问参数和方法
defineExpose({ reload, getChangeData,getFullFields }) 
</script>

<style lang="scss" scoped>
.field-editor-box {
    height: 100%;
    display: flex;
    flex-direction: column;

    .field-editor-toolbar {
        padding: 0px 5px 5px 5px;
    }

    .other-set-box {
        height: 200px;
        background: #fff;
        border-top: 1px solid #cdcdcd;
        padding: 10px;
    }
}
</style>